#include <iostream>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include "InetAddr.hpp"
#include "socket.hpp"
#include <functional>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <cstring>
#include "Log.hpp"
#include "TcpServer.hpp"
#include "protocol.hpp"
#include "Calcaulate.hpp"
using namespace protocol_ns;
using namespace socket_ns;

using calhander_t = std::function<Response(Request &req)>;
class Service
{
public:
    Service(calhander_t calexcute)
        : _calexcute(calexcute)
    {
    }
    void service(socket_ptr sockfd, InetAddr client_addr)
    {
        // 读取
        int fd = sockfd->SockFd();
        Log(DEBUG, "get a new link,ip:%s,port:%d,sockfd:%d", client_addr.IP().c_str(), client_addr.port(), fd);
        std::string packge;

        std::string recvmessage;
        // 长服务
        while (true)
        {
           // std::cout << "haaaaaaaaaa" << std::endl;
            sockfd->Recv(&recvmessage);
            while (true)
            {
                packge = Decode(recvmessage);
                // 如果本次解码后的包不是一个完整的包，需要再次接收
                if (packge.empty())
                {
                    //std::cout << "break啦" << std::endl;

                    break;
                }
                //Log(DEBUG, "decode success...");
                // 反序列化
                Request req;
                req.DeSerialize(packge);
                req.Debug();
                // 对请求做处理
                Response res = _calexcute(req);
                // 构建应答报文
                std::string send_mess;
                res.Serialize(&send_mess);
                //Log(DEBUG, "create response success...");
                std::string sendmessage = Encode(send_mess);
                std::cout << "sendmessage: " << send_mess << std::endl;
                sockfd->Send(sendmessage);
            }
        }
    }
    ~Service() {}

private:
    calhander_t _calexcute;
};

void Usage()
{
    std::cout << "Please Enter:\n"
              << "\tseverport";
}

int main(int argc, char *argv[])
{
    if (argc != 2)
    {
        Usage();
        exit(-1);
    }
    uint16_t port = std::stoi(argv[1]);
    Log(DEBUG, "create port success...");
    Calcaulate cal;
    Service calservice(std::bind(&Calcaulate::excute, &cal, std::placeholders::_1));
    io_service_t io_servcie = std::bind(&Service::service, &calservice, std::placeholders::_1, std::placeholders::_2);
    std::unique_ptr<TcpServer> server = std::make_unique<TcpServer>(port, io_servcie);
    // TcpServer server(port,service);
    server->start();
    return 0;
}